package com.kelin.calendarlistview.library;

import ohos.agp.window.service.Display;
import ohos.agp.window.service.DisplayAttributes;
import ohos.agp.window.service.DisplayManager;

import ohos.app.Context;

import java.text.ParseException;
import java.text.SimpleDateFormat;

import java.util.Calendar;
import java.util.Optional;
import java.util.TreeMap;

/**
 * CalendarHelper
 */
public final class CalendarHelper {
    private static final int ROW_ITEM_COUNT = 7;
    private static final int COLUMN_ITEM_COUNT = 6;
    public static final long ONE_DAY_TIME = 24 * 3600 * 1000L;

    private static float density;
    private static int width;
    private static int height;

    public static final SimpleDateFormat YEAR_MONTH_FORMAT = new SimpleDateFormat("yyyy-MM");
    public static final SimpleDateFormat YEAR_MONTH_DAY_FORMAT = new SimpleDateFormat("yyyy-MM-dd");

    private CalendarHelper() {
    }

    /**
     * getWidth
     *
     * @return int
     */
    public static int getWidth() {
        return width;
    }

    /**
     * getHeight
     *
     * @return int
     */
    public static int getHeight() {
        return height;
    }

    /**
     * init
     *
     * @param context 上下文
     */
    public static void init(Context context) {
        Optional<Display> display = DisplayManager.getInstance().getDefaultDisplay(context);
        DisplayAttributes displayAttributes = display.get().getAttributes();
        width = displayAttributes.width;
        height = displayAttributes.height;
        density = displayAttributes.densityPixels;
    }

    /**
     * 解析尺寸
     *
     * @param dimens 尺寸字符串
     * @return 尺寸值
     */
    public static float parseDimension(String dimens) {
        float dimensFloat = 0f;
        String newDimens = dimens.replace("vp", "").replace("fp", "");
        try {
            dimensFloat = Float.parseFloat(newDimens);
        } catch (NumberFormatException e) {
            e.printStackTrace();
        }
        return dimensFloat;
    }

    /**
     * vp转px
     *
     * @param context 上下文
     * @param dimens  尺寸字符串
     * @return px尺寸值
     */
    public static int vp2px(Context context, String dimens) {
        float vpValue = parseDimension(dimens);
        Display display = DisplayManager.getInstance().getDefaultDisplay(context).get();
        float dpi = display.getAttributes().densityPixels;
        return (int) (vpValue * dpi + 0.5 * (vpValue >= 0 ? 1 : -1));
    }

    /**
     * dp2px
     *
     * @param dp dp
     * @return int
     */
    public static int dp2px(int dp) {
        return (int) (dp * density);
    }

    /**
     * getDefaultCalendarDataListByMonthOffset
     *
     * @param yearMonth yearMonth
     * @param clazz clazz
     * @param <T> <T>
     * @return T extends BaseCalendarItemModel
     */
    public static <T extends BaseCalendarItemModel> TreeMap<String, T> getDefaultCalendarDataListByMonthOffset(String yearMonth, Class<T> clazz) {

        int calendarViewRow = COLUMN_ITEM_COUNT;
        int calendarViewColumn = ROW_ITEM_COUNT;

        Calendar calToday = Calendar.getInstance();
        Calendar calStartDate = Calendar.getInstance();
        calToday.setFirstDayOfWeek(Calendar.SUNDAY);
        calStartDate.setFirstDayOfWeek(Calendar.SUNDAY);
        long time = 0;
        try {
            time = YEAR_MONTH_FORMAT.parse(yearMonth).getTime();
        } catch (ParseException e) {
            e.printStackTrace();
        }
        calStartDate.setTimeInMillis(time);
        calStartDate.set(Calendar.DAY_OF_MONTH, 1);
        calStartDate.set(Calendar.HOUR_OF_DAY, 0);
        calStartDate.set(Calendar.MINUTE, 0);
        calStartDate.set(Calendar.SECOND, 0);
        Calendar activeCalendar = (Calendar) calStartDate.clone();
        calStartDate.add(Calendar.DAY_OF_WEEK, -(calStartDate.get(Calendar.DAY_OF_WEEK) - Calendar.SUNDAY));
        Calendar calEndDate = (Calendar) calStartDate.clone();
        calEndDate.add(Calendar.DAY_OF_MONTH, calendarViewRow * calendarViewColumn - 1);
        Calendar calCalendar = Calendar.getInstance();
        calCalendar.setTimeInMillis(calStartDate.getTimeInMillis());
        TreeMap<String, T> dayModelList = new TreeMap<>();
        if (calEndDate.get(Calendar.DAY_OF_MONTH) >= calendarViewColumn) {
            calendarViewRow--;
        }
        for (int i = 0; i < calendarViewRow * calendarViewColumn; i++) {
            T baseCalendarItemModel = null;
            try {
                baseCalendarItemModel = clazz.newInstance();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }

            if (baseCalendarItemModel != null) {
                baseCalendarItemModel.setCurrentMonth(areEqualMonth(calCalendar, activeCalendar));
                baseCalendarItemModel.setToday(areEqualDays(calCalendar.getTimeInMillis(), calToday.getTimeInMillis()));
                baseCalendarItemModel.setTimeMill(calCalendar.getTimeInMillis());
                baseCalendarItemModel.setHoliday(Calendar.SUNDAY == calCalendar.get(Calendar.DAY_OF_WEEK) ||
                        Calendar.SATURDAY == calCalendar.get(Calendar.DAY_OF_WEEK));
                baseCalendarItemModel.setDayNumber(String.valueOf(calCalendar.get(Calendar.DAY_OF_MONTH)));
                calCalendar.add(Calendar.DAY_OF_MONTH, 1);
                dayModelList.put(YEAR_MONTH_DAY_FORMAT.format(
                        baseCalendarItemModel.getTimeMill()), (T) baseCalendarItemModel);
            }
        }

        return dayModelList;
    }

    /**
     * getCalendarByYearMonth
     *
     * @param yearMonth yearMonth
     * @return Calendar
     */
    public static Calendar getCalendarByYearMonth(String yearMonth) {
        Calendar calendar = Calendar.getInstance();
        try {
            calendar.setTimeInMillis(CalendarHelper.YEAR_MONTH_FORMAT.parse(yearMonth).getTime());
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return calendar;
    }

    /**
     * getCalendarByYearMonthDay
     *
     * @param yearMonthDay yearMonthDay
     * @return Calendar
     */
    public static Calendar getCalendarByYearMonthDay(String yearMonthDay) {
        Calendar calendar = Calendar.getInstance();
        try {
            calendar.setTimeInMillis(CalendarHelper.YEAR_MONTH_DAY_FORMAT.parse(yearMonthDay).getTime());
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return calendar;
    }

    /**
     * areEqualDays
     *
     * @param time1 time1
     * @param time2 time2
     * @return boolean
     */
    public static boolean areEqualDays(long time1, long time2) {
        SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy");
        return (sdf.format(time1).equals(sdf.format(time2)));
    }

    /**
     * areEqualMonth
     *
     * @param c1 Calendar
     * @param c2 Calendar
     * @return boolean
     */
    public static boolean areEqualMonth(Calendar c1, Calendar c2) {
        SimpleDateFormat sdf = new SimpleDateFormat("MM-yyyy");
        return (sdf.format(c1.getTime()).equals(sdf.format(c2.getTime())));
    }

    /**
     * getDiffDayByTimeStamp
     *
     * @param startTimeStamp startTimeStamp
     * @param endTimeStamp endTimeStamp
     * @return int
     */
    public static int getDiffDayByTimeStamp(long startTimeStamp, long endTimeStamp) {
        return Math.round((endTimeStamp - startTimeStamp) * 1.0f / ONE_DAY_TIME);
    }

    /**
     * getDiffMonthByTime
     *
     * @param startTime startTime
     * @param endTime endTime
     * @return int
     */
    public static int getDiffMonthByTime(String startTime, String endTime) {
        Calendar startCalendar = getCalendarByYearMonthDay(startTime);
        Calendar endCalendar = getCalendarByYearMonthDay(endTime);
        return (12 * (endCalendar.get(Calendar.YEAR) - startCalendar.get(Calendar.YEAR))) +
                endCalendar.get(Calendar.MONTH) - startCalendar.get(Calendar.MONTH);
    }
}
